home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / comm / tcp / IPDial1_3.lha / ipdial / Serial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-03  |  15.0 KB  |  697 lines

  1. /**
  2. ***  IPDial    Script program for initializing a SLIP connection
  3. ***  Copyright    (C)   1994    Jochen Wiedmann
  4. ***
  5. ***  This program is free software; you can redistribute it and/or modify
  6. ***  it under the terms of the GNU General Public License as published by
  7. ***  the Free Software Foundation; either version 2 of the License, or
  8. ***  (at your option) any later version.
  9. ***
  10. ***  This program is distributed in the hope that it will be useful,
  11. ***  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ***  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ***  GNU General Public License for more details.
  14. ***
  15. ***  You should have received a copy of the GNU General Public License
  16. ***  along with this program; if not, write to the Free Software
  17. ***  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ***
  19. ***
  20. ***
  21. ***  This file implements the communication with the serial.device.
  22. ***
  23. ***
  24. ***  Computer: Amiga 1200            Compiler: Dice 3.01
  25. ***
  26. ***  Author:    Jochen Wiedmann
  27. ***        Am Eisteich 9
  28. ***        72555 Metzingen
  29. ***        Germany
  30. ***
  31. ***        Phone: (+0049) 7123 / 14881
  32. ***        Internet: jochen.wiedmann@uni-tuebingen.de
  33. **/
  34.  
  35.  
  36.  
  37.  
  38.  
  39. /**
  40. ***  Include files
  41. **/
  42. #ifndef IPDIAL_H
  43. #include "IPDial.h"
  44. #endif
  45. #include <ctype.h>
  46. #include <devices/serial.h>
  47. #include <devices/timer.h>
  48.  
  49. #ifndef MIN
  50. #define MIN(a,b) (((a)>(b))?(b):(a))
  51. #endif
  52.  
  53.  
  54.  
  55.  
  56.  
  57. /**
  58. ***  Local variables.
  59. **/
  60. STATIC APTR MySerReq        = NULL;
  61. STATIC APTR MyTimeReq        = NULL;
  62. STATIC APTR InputFile        = NULL;
  63. STATIC UBYTE SerBuffer[4096];
  64.  
  65.  
  66.  
  67.  
  68. /**
  69. ***  Cleanup function.
  70. **/
  71. VOID SerialCleanup(VOID)
  72.  
  73. { DeviceIODelete(MySerReq);
  74.   DeviceIODelete(MyTimeReq);
  75. }
  76.  
  77.  
  78.  
  79.  
  80.  
  81. /**
  82. ***  Table of error messages created by the serial.device.
  83. **/
  84. STATIC VOID SerialShowError(ULONG Error)
  85.  
  86. { STRPTR ptr;
  87.  
  88.   switch(Error)
  89.   { case 1:
  90.       ptr = (STRPTR) "Serial device busy";
  91.       break;
  92.     case 2:
  93.       ptr = (STRPTR) "Baud rate not supported";
  94.       break;
  95.     case 4:
  96.       ptr = (STRPTR) "Memory error";
  97.       break;
  98.     case 5:
  99.       ptr = (STRPTR) "Invalid parameters";
  100.       break;
  101.     case 6:
  102.       ptr = (STRPTR) "Line error";
  103.       break;
  104.     case 9:
  105.       ptr = (STRPTR) "Parity error";
  106.       break;
  107.     case 11:
  108.       ptr = (STRPTR) "Timer error";
  109.       break;
  110.     case 12:
  111.       ptr = (STRPTR) "Buffer overflow";
  112.       break;
  113.     case 13:
  114.       ptr = (STRPTR) "No DSR";
  115.       break;
  116.     case 15:
  117.       ptr = (STRPTR) "Break detected";
  118.       break;
  119.     default:
  120.       ptr = (STRPTR) "Unknown error";
  121.       break;
  122.   }
  123.  
  124.   fprintf(stderr, "Serial device: %s.\n", ptr);
  125. }
  126.  
  127.  
  128.  
  129.  
  130.  
  131. /**
  132. ***  This function opens the serial device. It can be closed
  133. ***  using DeviceIODelete().
  134. **/
  135. STATIC ULONG SerialDecodeProtocol(struct IOExtSer *SerReq, STRPTR Protocol)
  136.  
  137. { if (stricmp((char *) Protocol, "XONXOFF") == 0)
  138.   { SerReq->io_SerFlags &= ~(SERF_XDISABLED|SERF_7WIRE);
  139.   }
  140.   else if (stricmp((char *) Protocol, "NONE") == 0)
  141.   { SerReq->io_SerFlags |= SERF_XDISABLED;
  142.     SerReq->io_SerFlags &= ~SERF_7WIRE;
  143.   }
  144.   else if (stricmp((char *) Protocol, "RTSCTS") == 0  ||
  145.        stricmp((char *) Protocol, "7WIRE") == 0)
  146.   { SerReq->io_SerFlags |= (SERF_XDISABLED|SERF_7WIRE);
  147.   }
  148.   else
  149.   { return(FALSE);
  150.   }
  151.   return(TRUE);
  152. }
  153.  
  154.  
  155.  
  156.  
  157.  
  158. ULONG SerialOpen(STRPTR DeviceName, STRPTR Protocol, ULONG Unit)
  159.  
  160. { ULONG error;
  161.   struct IOExtSer *RealSerReq;
  162.  
  163.   if (!(MySerReq = DeviceIOCreate(sizeof(struct IOExtSer))))
  164.   { fprintf(stderr, "Failed to open %s: Memory error.\n",
  165.         DeviceName);
  166.     exit(10);
  167.   }
  168.   RealSerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  169.   RealSerReq->io_SerFlags = 0;
  170.   if (Protocol)
  171.   { if (!SerialDecodeProtocol(RealSerReq, Protocol))
  172.     { return(FALSE);
  173.     }
  174.   }
  175.   if ((error = DeviceIOOpen(DeviceName, Unit, MySerReq, 0)))
  176.   { SerialShowError(error);
  177.     exit(10);
  178.   }
  179.   if(Protocol)
  180.   { SerialSetProtocol(Protocol);
  181.   }
  182.  
  183.   if (!(MyTimeReq = DeviceIOCreate(sizeof(struct timerequest))))
  184.   { fprintf(stderr, "Failed to open timer.device: Memory error.\n");
  185.     exit(10);
  186.   }
  187.   if ((error = DeviceIOOpen((STRPTR) "timer.device", UNIT_VBLANK,
  188.                      MyTimeReq, 0)))
  189.   { fprintf(stderr, "Failed to open timer.device: Error %ld\n", error);
  190.     exit(10);
  191.   }
  192.   return(TRUE);
  193. }
  194.  
  195.  
  196.  
  197.  
  198.  
  199. /**
  200. ***  This function sends a string to the serial device.
  201. ***  This is somewhat nasty, as the string must be preparsed first.
  202. **/
  203. VOID SerialSend(STRPTR str, ULONG len)
  204.  
  205. { struct IOExtSer *req;
  206.   STRPTR ptr;
  207.   STATIC APTR sendBuffer = NULL;
  208.  
  209.   /**
  210.   ***  Be sure, that the buffer is valid.
  211.   **/
  212.   if (!sendBuffer  &&  !(sendBuffer = BufferCreate()))
  213.   { perror("malloc");
  214.     exit(10);
  215.   }
  216.  
  217.   /**
  218.   ***  Clear the buffer.
  219.   **/
  220.   BufferClear(sendBuffer);
  221.  
  222.   /**
  223.   ***  Parse the string.
  224.   **/
  225.   while(len)
  226.   { ptr = str;
  227.     while (len  &&  *ptr != '$')
  228.     { --len;
  229.       ++ptr;
  230.     }
  231.     BufferExtend(sendBuffer, str, ptr-str);
  232.     str = ptr;
  233.  
  234.     if (len)    /*  '$' found   */
  235.     { --len;    /*  Skip '$'    */
  236.       ++str;
  237.       if (len)
  238.       { if (*str == '$')    /*  Is it a "$$"?   */
  239.     { BufferExtend(sendBuffer, "$", 1);
  240.       --len;
  241.       ++str;
  242.     }
  243.     else            /*    No, look for variable name. */
  244.     { int varNameLen;
  245.       char *varName;
  246.       char *varVal;
  247.  
  248.       if (*str == '{')
  249.       { --len;    /*  Skip '{'    */
  250.         ++str;
  251.         varName = str;
  252.         while (len  &&  *str != '}')
  253.         { --len;
  254.           ++str;
  255.         }
  256.         varNameLen = (char *) str - varName;
  257.         if (len)
  258.         { --len;    /*  Skip '}'    */
  259.           ++str;
  260.         }
  261.       }
  262.       else
  263.       { varName = str;
  264.         while(len  &&  isalpha(*str))
  265.         { --len;
  266.           ++str;
  267.         }
  268.         varNameLen = (char *) str - varName;
  269.       }
  270.  
  271.       if (!(ptr = malloc(varNameLen+1)))
  272.       { perror("malloc");
  273.         exit(10);
  274.       }
  275.       strncpy(ptr, varName, varNameLen+1);
  276.       ptr[varNameLen] = '\0';
  277.       if ((varVal = getenv(ptr)))
  278.       { BufferExtend(sendBuffer, varVal, strlen(varVal));
  279.       }
  280.     }
  281.       }
  282.     }
  283.   }
  284.  
  285. #ifdef DEBUG
  286.   printf("SerialSend: %s\n", BufferBuffer(sendBuffer));
  287. #endif
  288.   req = (struct IOExtSer *) DeviceIOReq(MySerReq);
  289.   req->IOSer.io_Length = strlen(BufferBuffer(sendBuffer));
  290.   req->IOSer.io_Data = BufferBuffer(sendBuffer);
  291.   DeviceIODo(MySerReq, CMD_WRITE);
  292. }
  293.  
  294.  
  295.  
  296.  
  297.  
  298. /**
  299. ***  This function is used to wait for a certain string.
  300. ***
  301. ***  The function will return if either a timeout occurs
  302. ***  (never happens, if timeout == -1) or if one of the
  303. ***  strings in the args array is read from the serial.device.
  304. ***
  305. ***  Result is the number of the string or -1.
  306. **/
  307. LONG SerialWait(STRPTR *args, LONG timeout)
  308.  
  309. { ULONG sigs;
  310.   ULONG rsigs;
  311.   BYTE error;
  312.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  313.   STATIC APTR waitBuffer = NULL;
  314.  
  315.   /**
  316.   ***  Be sure, that the buffer is valid.
  317.   **/
  318.   if (!waitBuffer  &&  !(waitBuffer = BufferCreate()))
  319.   { perror("malloc");
  320.     exit(10);
  321.   }
  322.  
  323.   /**
  324.   ***  Clear the buffer.
  325.   **/
  326.   BufferClear(waitBuffer);
  327.  
  328.   sigs = SIGBREAKF_CTRL_C | DeviceIOSignal(MySerReq);
  329.  
  330.   if (timeout != -1)
  331.   { struct timerequest *tr = (struct timerequest *) DeviceIOReq(MyTimeReq);
  332.  
  333.     tr->tr_time.tv_secs = timeout;
  334.     tr->tr_time.tv_micro = 0;
  335.     DeviceIOSend(MyTimeReq, TR_ADDREQUEST);
  336.     sigs |= DeviceIOSignal(MyTimeReq);
  337.   }
  338.  
  339.   for(;;)
  340.   { LONG result;
  341.  
  342.     /**
  343.     ***  First ask, if any data is present on the serial line.
  344.     ***  May be, the string we are waiting for is already present?
  345.     **/
  346.     do
  347.     { DeviceIODo(MySerReq, SDCMD_QUERY);
  348.       if ((result = SerReq->IOSer.io_Actual))
  349.       { SerReq->IOSer.io_Data = SerBuffer;
  350.     SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1, SerReq->IOSer.io_Actual);
  351.     if ((error = DeviceIODo(MySerReq, CMD_READ)))
  352.     { SerialShowError(error);
  353.       exit(10);
  354.     }
  355.     if (EchoMode)
  356.     { int i;
  357.  
  358.       for (i = 0;  i < SerReq->IOSer.io_Actual;  i++)
  359.       { putchar(SerBuffer[i]);
  360.       }
  361.       fflush(stdout);
  362.     }
  363.     BufferExtend(waitBuffer, SerBuffer, SerReq->IOSer.io_Actual);
  364.       }
  365.     }
  366.     while (result);
  367.  
  368.  
  369.     if ((result = BufferCheck(waitBuffer, args)) >= 0)
  370.     { DeviceIOAbort(MyTimeReq);
  371.       return(result);
  372.     }
  373.  
  374.     /**
  375.     ***  It isn't, send a request for one byte.
  376.     **/
  377.     SerReq->IOSer.io_Length = 1;
  378.     SerReq->IOSer.io_Data = SerBuffer;
  379.     DeviceIOSend(MySerReq, CMD_READ);
  380.  
  381.     rsigs = Wait(sigs);
  382.  
  383.     if (rsigs & SIGBREAKF_CTRL_C)
  384.     { printf("Ctrl-C\n");
  385.       exit(10);
  386.     }
  387.     else if (rsigs & DeviceIOSignal(MySerReq))
  388.     { BYTE error;
  389.  
  390.       /**
  391.       ***  Data received, add it to the buffer and check for more.
  392.       **/
  393.       if ((error = DeviceIOWait(MySerReq)))
  394.       { SerialShowError(error);
  395.     exit(10);
  396.       }
  397.       if (EchoMode)
  398.       { putchar(*SerBuffer);
  399.     fflush(stdout);
  400.       }
  401.       BufferExtend(waitBuffer, SerBuffer, 1);
  402.     }
  403.     else
  404.     { /**
  405.       ***  Timeout
  406.       **/
  407.       DeviceIOWait(MyTimeReq);
  408.       DeviceIOAbort(MySerReq);
  409.       return(-1);
  410.     }
  411.   }
  412. }
  413.  
  414.  
  415.  
  416.  
  417.  
  418. /**
  419. ***  This function implements a terminal mode. It gives the users input
  420. ***  to the modem and likewise the modems output to the user, as long as
  421. ***  the user doesn't enter Ctrl-\.
  422. **/
  423. VOID SerialTerminal(VOID)
  424.  
  425. { struct DosPacket *dp = NULL;
  426.   struct MsgPort *port = NULL;
  427.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  428.   APTR SerSendReq = NULL;
  429.   struct IOExtSer *serSendReq;
  430.   char buffer[128];
  431.   ULONG status = 10;
  432.   BPTR cis = Input();
  433.   ULONG sigs;
  434.   ULONG serSent = FALSE;
  435.  
  436.   if (!cis)
  437.   { fprintf(stderr, "Can't use nil: as input device.\n");
  438.     exit(10);
  439.   }
  440.  
  441.   if ((dp = AllocDosObject(DOS_STDPKT, NULL)))
  442.   { if ((port = CreateMsgPort()))
  443.     { if ((SerSendReq = DeviceIOCreate(sizeof(struct IOExtSer))))
  444.       { serSendReq = (struct IOExtSer *) DeviceIOReq(SerSendReq);
  445.     serSendReq->IOSer.io_Device = SerReq->IOSer.io_Device;
  446.     serSendReq->IOSer.io_Unit = SerReq->IOSer.io_Device;
  447.     status = 0;
  448.       }
  449.     }
  450.   }
  451.  
  452.   if (status)
  453.   { fprintf(stderr, "Memory error.\n");
  454.     goto ExitSerialTerminal;
  455.   }
  456.  
  457.   dp->dp_Type = ACTION_READ;
  458.   dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
  459.   dp->dp_Arg2 = (ULONG) buffer;
  460.   dp->dp_Arg3 = sizeof(buffer);
  461.   SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type, port);
  462.  
  463.   SerReq->IOSer.io_Length = 1;
  464.   SerReq->IOSer.io_Data = SerBuffer;
  465.   DeviceIOSend(MySerReq, CMD_READ);
  466.  
  467.   sigs = (1 << port->mp_SigBit) | SIGBREAKF_CTRL_C | DeviceIOSignal(MySerReq);
  468.  
  469.   for(;;)
  470.   { LONG rsigs;
  471.  
  472.     rsigs = Wait(sigs);
  473.  
  474.     if (rsigs & SIGBREAKF_CTRL_C)
  475.     { fprintf(stderr, "Ctrl-C\n");
  476.       status = 5;
  477.       DeviceIOAbort(MySerReq);
  478.       AbortPkt(port, dp);
  479.       WaitPort(port);
  480.       goto ExitSerialTerminal;
  481.     }
  482.  
  483.     if (rsigs & (1 << port->mp_SigBit))
  484.     { GetMsg(port);
  485.       if (dp->dp_Res1 == -1)
  486.       { fprintf(stderr, "Error %ld while reading input.\n", dp->dp_Res2);
  487.     status = 10;
  488.       }
  489.       if (dp->dp_Res1 == -1  ||  dp->dp_Res1 == 0)
  490.       { DeviceIOAbort(MySerReq);
  491.     goto ExitSerialTerminal;
  492.       }
  493.  
  494.       serSendReq->IOSer.io_Length = dp->dp_Res1;
  495.       serSendReq->IOSer.io_Data = buffer;
  496.       DeviceIODo(SerSendReq, CMD_WRITE);
  497.  
  498.       dp->dp_Type = ACTION_READ;
  499.       dp->dp_Arg1 = ((struct FileHandle *) BADDR(cis))->fh_Arg1;
  500.       dp->dp_Arg2 = (ULONG) buffer;
  501.       dp->dp_Arg3 = sizeof(buffer);
  502.       SendPkt(dp, (struct MsgPort *) ((struct FileHandle *) BADDR(cis))->fh_Type, port);
  503.     }
  504.  
  505.     if (rsigs & DeviceIOSignal(MySerReq))
  506.     { LONG error;
  507.       LONG result;
  508.  
  509.       if ((error = DeviceIOWait(MySerReq)))
  510.       { SerialShowError(error);
  511.     AbortPkt(port, dp);
  512.     WaitPort(port);
  513.     goto ExitSerialTerminal;
  514.       }
  515.       putchar(*SerBuffer);
  516.  
  517.       do
  518.       { DeviceIODo(MySerReq, SDCMD_QUERY);
  519.     if ((result = SerReq->IOSer.io_Actual))
  520.     { SerReq->IOSer.io_Data = SerBuffer;
  521.       SerReq->IOSer.io_Length = MIN(sizeof(SerBuffer)-1, SerReq->IOSer.io_Actual);
  522.       if ((error = DeviceIODo(MySerReq, CMD_READ)))
  523.       { SerialShowError(error);
  524.         exit(10);
  525.       }
  526.       fwrite(SerBuffer, SerReq->IOSer.io_Actual, 1, stdout);
  527.       fflush(stdout);
  528.     }
  529.       }
  530.       while (result);
  531.  
  532.       SerReq->IOSer.io_Length = 1;
  533.       SerReq->IOSer.io_Data = SerBuffer;
  534.       DeviceIOSend(MySerReq, CMD_READ);
  535.     }
  536.   }
  537.  
  538.  
  539. ExitSerialTerminal:
  540.   if (dp)
  541.   { FreeDosObject(DOS_STDPKT, dp);
  542.   }
  543.   if (port)
  544.   { DeleteMsgPort(port);
  545.   }
  546.   if (SerSendReq)
  547.   { DeviceIODelete(SerSendReq);
  548.   }
  549.   if (status)
  550.   { exit(status);
  551.   }
  552. }
  553.  
  554.  
  555.  
  556.  
  557.  
  558. /**
  559. ***  This function shows the current serial parameters.
  560. **/
  561. VOID SerialShowParms(VOID)
  562.  
  563. { STRPTR Parity, Protocol;
  564.   struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  565.  
  566.   printf("\tBaud = %ld\n", SerReq->io_Baud);
  567.   printf("\tDataBits = %ld\n", (ULONG) SerReq->io_ReadLen);
  568.   printf("\tStopBits = %ld\n", (ULONG) SerReq->io_StopBits);
  569.   printf("\tBufSize = %ld\n", SerReq->io_RBufLen);
  570.   if (SerReq->io_SerFlags & SERF_PARTY_ON)
  571.   { if (SerReq->io_SerFlags & SERF_PARTY_ODD)
  572.     { Parity = (STRPTR) "Odd";
  573.     }
  574.     else
  575.     { Parity = (STRPTR) "Even";
  576.     }
  577.   }
  578.   else
  579.   { Parity = (STRPTR) "None";
  580.   }
  581.   printf("\tParity = %s\n", Parity);
  582.   if (SerReq->io_SerFlags & SERF_7WIRE)
  583.   { if (SerReq->io_SerFlags & SERF_XDISABLED)
  584.     { Protocol = (STRPTR) "RTS/CTS";
  585.     }
  586.     else
  587.     { Protocol = (STRPTR) "RTS/CTS, XON/XOFF";
  588.     }
  589.   }
  590.   else
  591.   { if (SerReq->io_SerFlags & SERF_XDISABLED)
  592.     { Protocol = (STRPTR) "None";
  593.     }
  594.     else
  595.     { Protocol = (STRPTR) "XON/XOFF";
  596.     }
  597.   }
  598.   printf("\tProtocol = %s\n\n", Protocol);
  599. }
  600.  
  601.  
  602.  
  603.  
  604.  
  605. /**
  606. ***  Some functions for setting serial parameters.
  607. **/
  608. VOID SerialSetBaud(ULONG Baud)
  609.  
  610. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  611.   BYTE error;
  612.  
  613.   SerReq->io_Baud = Baud;
  614.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  615.   { SerialShowError(error);
  616.     exit(10);
  617.   }
  618. }
  619. VOID SerialSetDataBits(UBYTE DataBits)
  620.  
  621. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  622.   BYTE error;
  623.  
  624.   SerReq->io_ReadLen = SerReq->io_WriteLen = DataBits;
  625.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  626.   { SerialShowError(error);
  627.     exit(10);
  628.   }
  629. }
  630. VOID SerialSetStopBits(UBYTE StopBits)
  631.  
  632. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  633.   BYTE error;
  634.  
  635.   SerReq->io_StopBits = StopBits;
  636.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  637.   { SerialShowError(error);
  638.     exit(10);
  639.   }
  640. }
  641. VOID SerialSetBufSize(ULONG BufSize)
  642.  
  643. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  644.   BYTE error;
  645.  
  646.   if (BufSize & 0x3f)
  647.   { fprintf(stderr,
  648.         "Warning: BufSize must be a multiple of 64, rounding up.\n");
  649.     BufSize = (BufSize & 0x3f) + 0x40;
  650.   }
  651.   SerReq->io_RBufLen = BufSize;
  652.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  653.   { SerialShowError(error);
  654.     exit(10);
  655.   }
  656. }
  657. ULONG SerialSetParity(STRPTR Parity)
  658.  
  659. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  660.   BYTE error;
  661.  
  662.   if (stricmp((char *) Parity, "NONE") == 0)
  663.   { SerReq->io_SerFlags &= ~SERF_PARTY_ON;
  664.   }
  665.   else if (stricmp((char *) Parity, "EVEN") == 0)
  666.   { SerReq->io_SerFlags |= SERF_PARTY_ON;
  667.     SerReq->io_SerFlags &= ~SERF_PARTY_ODD;
  668.   }
  669.   else if (stricmp((char *) Parity, "ODD") == 0)
  670.   { SerReq->io_SerFlags |= (SERF_PARTY_ON|SERF_PARTY_ODD);
  671.   }
  672.   else
  673.   { return(FALSE);
  674.   }
  675.  
  676.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  677.   { SerialShowError(error);
  678.     exit(10);
  679.   }
  680.   return(TRUE);
  681. }
  682. ULONG SerialSetProtocol(STRPTR Protocol)
  683.  
  684. { struct IOExtSer *SerReq = (struct IOExtSer *) DeviceIOReq(MySerReq);
  685.   BYTE error;
  686.  
  687.   if (!(SerialDecodeProtocol(SerReq, Protocol)))
  688.   { return(FALSE);
  689.   }
  690.  
  691.   if ((error = DeviceIODo(MySerReq, SDCMD_SETPARAMS)))
  692.   { SerialShowError(error);
  693.     exit(10);
  694.   }
  695.   return(TRUE);
  696. }
  697.